<template>
  <div>
    <!-- 图片批注弹窗 -->
    <el-dialog
      title="手绘批注"
      :visible.sync="visible"
      :append-to-body="true"
      :close-on-click-modal="false"
      :modal-append-to-body="true"
      :close-on-press-escape="true"
      width="800px"
      class="annotation-dialog"
      @close="handleClose">
      <div class="annotation-editor" v-if="visible">
        <div class="canvas-container">
          <canvas ref="annotationCanvas" :width="canvasWidth" :height="canvasHeight" 
            @mousedown="startDrawing" @mousemove="draw" @mouseup="stopDrawing" @mouseout="stopDrawing"></canvas>
        </div>
        
        <div class="annotation-tools">
          <div class="tool-group">
            <div class="tool-label">画笔颜色：</div>
            <el-color-picker v-model="annotationColor" size="small"></el-color-picker>
          </div>
          
          <div class="tool-group">
            <div class="tool-label">画笔粗细：</div>
            <el-slider v-model="lineWidth" :min="1" :max="10" :step="1"></el-slider>
          </div>
          
          <div class="button-group">
            <el-button type="primary" @click="saveAnnotation">保存批注</el-button>
            <el-button @click="clearAnnotation">清除批注</el-button>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'ImageAnnotator',
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    imageData: {
      type: [Object, null],
      default: null
    },
    imageIndex: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      annotationColor: '#FF0000',
      lineWidth: 3, // 画笔粗细
      canvasWidth: 760,
      canvasHeight: 400,
      currentImage: null,
      preloadedImage: null, // 预加载的图片对象
      isDrawing: false,
      lastX: 0, // 上一次绘制的X坐标
      lastY: 0, // 上一次绘制的Y坐标
      ctx: null
    };
  },
  watch: {
    visible(newVal) {
      if (newVal && this.imageData) {
        this.$nextTick(() => {
          this.loadImage();
        });
      }
    },
    imageData(newVal) {
      if (this.visible && newVal) {
        this.$nextTick(() => {
          this.loadImage();
        });
      }
    }
  },
  methods: {
    // 加载图片
    loadImage() {
      // 显示加载中
      const loadingMessage = this.$message({
        message: '正在加载图片数据...',
        type: 'info',
        duration: 0
      });
      
      this.preloadImageData().then(img => {
        loadingMessage.close();
        this.drawImageWhenReady(img);
      }).catch(error => {
        loadingMessage.close();
        console.error('图片加载失败:', error);
        this.$message.error('无法加载图片: ' + error.message);
      });
    },
    
    // 预加载图片数据
    preloadImageData() {
      return new Promise((resolve, reject) => {
        if (!this.imageData) {
          reject(new Error('没有提供图片数据'));
          return;
        }
        
        // 获取图片URL
        let imgUrl = null;
        
        // 尝试从文件对象获取
        if (this.imageData.raw) {
          imgUrl = URL.createObjectURL(this.imageData.raw);
        } 
        // 使用已有URL
        else if (this.imageData.url) {
          imgUrl = this.imageData.url;
        }
        
        if (!imgUrl) {
          reject(new Error('无法获取图片URL'));
          return;
        }
        
        // 创建图片对象
        const img = new Image();
        img.crossOrigin = "anonymous"; // 允许跨域
        
        // 图片加载成功
        img.onload = () => {
          resolve(img);
        };
        
        // 图片加载失败
        img.onerror = () => {
          // 如果是使用的现有URL失败，尝试用FileReader读取
          if (this.imageData.raw) {
            const reader = new FileReader();
            reader.onload = (e) => {
              const newImg = new Image();
              newImg.onload = () => resolve(newImg);
              newImg.onerror = () => reject(new Error('FileReader加载图片失败'));
              newImg.src = e.target.result;
            };
            reader.onerror = () => reject(new Error('读取图片文件失败'));
            reader.readAsDataURL(this.imageData.raw);
          } else {
            reject(new Error('图片加载失败'));
          }
        };
        
        // 设置图片源
        img.src = imgUrl;
      });
    },
    
    // 当对话框准备好时绘制图片
    drawImageWhenReady(img) {
      // 使用递归检查直到canvas准备好
      const checkAndDraw = () => {
        if (!this.$refs.annotationCanvas) {
          // 如果画布还没准备好，100ms后再检查
          setTimeout(checkAndDraw, 100);
          return;
        }
        
        // 画布已准备好，进行绘制
        const canvas = this.$refs.annotationCanvas;
        this.ctx = canvas.getContext('2d');
        
        if (!this.ctx) {
          this.$message.error('无法获取画布上下文');
          return;
        }
        
        // 调整canvas尺寸以适应图片
        const aspectRatio = img.width / img.height;
        if (aspectRatio > 1) {
          // 宽图
          this.canvasWidth = 760;
          this.canvasHeight = this.canvasWidth / aspectRatio;
        } else {
          // 高图
          this.canvasHeight = 400;
          this.canvasWidth = this.canvasHeight * aspectRatio;
        }
        
        // 重设canvas尺寸
        canvas.width = this.canvasWidth;
        canvas.height = this.canvasHeight;
        
        // 清空画布
        this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
        
        try {
          // 绘制图片
          this.ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight);
          
          // 保存当前图片
          this.currentImage = img;
        } catch (error) {
          console.error('绘制图片到画布失败:', error);
          this.$message.error('绘制图片失败: ' + error.message);
        }
      };
      
      // 开始检查
      checkAndDraw();
    },
    
    // 开始绘制
    startDrawing(e) {
      if (!this.ctx) return;
      
      this.isDrawing = true;
      
      // 获取鼠标相对于画布的位置
      const rect = this.$refs.annotationCanvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      
      // 记录开始位置
      this.lastX = x;
      this.lastY = y;
      
      // 设置画笔样式
      this.ctx.strokeStyle = this.annotationColor;
      this.ctx.lineWidth = this.lineWidth;
      this.ctx.lineCap = 'round';
      this.ctx.lineJoin = 'round';
    },
    
    // 绘制
    draw(e) {
      if (!this.isDrawing || !this.ctx) return;
      
      // 获取鼠标相对于画布的位置
      const rect = this.$refs.annotationCanvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      
      // 绘制线条
      this.ctx.beginPath();
      this.ctx.moveTo(this.lastX, this.lastY);
      this.ctx.lineTo(x, y);
      this.ctx.stroke();
      
      // 更新位置
      this.lastX = x;
      this.lastY = y;
    },
    
    // 停止绘制
    stopDrawing() {
      this.isDrawing = false;
    },
    
    // 刷新画布
    refreshCanvas() {
      if (!this.ctx || !this.currentImage) return;
      
      // 清空画布
      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      
      // 重新绘制背景图片
      this.ctx.drawImage(this.currentImage, 0, 0, this.canvasWidth, this.canvasHeight);
    },
    
    // 清除批注
    clearAnnotation() {
      if (!this.ctx || !this.currentImage) return;
      
      // 刷新画布，恢复到只有背景图片的状态
      this.refreshCanvas();
    },
    
    // 保存批注
    saveAnnotation() {
      if (!this.ctx) return;
      
      // 将画布转换为图片数据
      const imageData = this.$refs.annotationCanvas.toDataURL('image/png');
      
      // 将图片数据转为blob
      const blob = this.dataURLtoBlob(imageData);
      
      // 发送保存事件到父组件
      this.$emit('save', {
        blob: blob,
        index: this.imageIndex
      });
      
      // 关闭对话框
      this.$emit('update:visible', false);
    },
    
    // 处理对话框关闭
    handleClose() {
      this.$emit('update:visible', false);
      this.$emit('close');
    },
    
    // 工具方法：将dataURL转换为Blob
    dataURLtoBlob(dataURL) {
      // 将base64格式的dataURL转换为Blob对象
      const arr = dataURL.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    }
  }
};
</script>

<style lang="scss">
// 批注对话框样式
.annotation-dialog {
  z-index: 10001 !important;
  
  .el-dialog__wrapper {
    z-index: 10001 !important;
  }
  
  .el-dialog__body {
    padding: 10px 20px;
  }
  
  .annotation-editor {
    display: flex;
    flex-direction: column;
    
    .canvas-container {
      width: 100%;
      margin-bottom: 15px;
      border: 1px solid #eee;
      text-align: center;
      min-height: 200px;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: #f5f7fa;
      
      canvas {
        cursor: crosshair;
        display: block;
        margin: 0 auto;
      }
    }
    
    .annotation-tools {
      padding: 10px 0;
      
      .tool-group {
        display: flex;
        align-items: center;
        margin-bottom: 10px;
        
        .tool-label {
          width: 80px;
          font-size: 14px;
          color: #606266;
        }
        
        .el-input, .el-color-picker {
          width: 180px;
        }
        
        .el-slider {
          width: 300px;
          margin-left: 10px;
        }
      }
      
      .button-group {
        margin-top: 20px;
        text-align: right;
      }
    }
  }
}
</style> 